#pragma once
#include "Connection.hpp"
#include<iostream>
#include <sys/types.h>
#include <sys/socket.h>

class Reactor;

class Channel : public Connection
{
public:
    Channel(int sockfd, InetAddr clientaddr)
    {
        SetSockfd(sockfd);
        SetClientAddr(clientaddr);
        // 设置相关属性，例如关心的事件,own 在Reactor 中内部设置
        SetEvents(EPOLLIN | EPOLLET);
    }
    ~Channel() {}

    void Recver()
    {
        // 普通sockfd 从读取数据
        // 因为为ET模式，所以需要循环读取数据，一次性将数据读取完
        while (true)
        {
            char buffer[1024];
            ssize_t n = recv(_sockfd , buffer , sizeof(buffer)-1 , 0);
            if(n > 0)
            {
                //成功读取到数据
                buffer[n]=0;
                _inbuffer+=buffer;
            }
            else if(n == 0)
            {
                //对端关闭，交给异常处理，统一异常处理
                LOG(LogLevel::INFO) << "对端关闭 , me too";
                Excepter();
            }
            else
            {
                //返回值小于0，需要对错误码进行判断处理
                //可能是读完了，也有可能是信号中断，也有可能真的是错误
                if(errno == EAGAIN)
                {
                    break;
                }
                else if(errno == EINTR)
                {
                    continue;
                }
                else
                {
                    LOG(LogLevel::INFO) << "recv error, client is:" << _peer.ToString();
                    Excepter();//异常处理统一
                    return;
                }
            }
        }

        //走到此处就说明数据读取完了
        //将数据交给上层进行处理
        _outbuffer += _cb(_inbuffer);
        //判断是否为空，不为空就直接调用Sender()
        // if(!_outbuffer.empty())
        //     Sender();

        //还有一种处理方法，使能写关心
        if(!_outbuffer.empty())
             Owner()->EnableReadWrite(_sockfd , true,true);
    }

    void Sender() 
    {
        //发送数据也需要循环发送
        while(true)
        {
            ssize_t n = send(_sockfd , _outbuffer.c_str() , _outbuffer.size() , 0);
            if(n >=0 )
            {
                //发送成功,将成功发送出去的数据从_outbuffer 中移除
                _outbuffer.erase(0,n);
                //判断是否发送完成
                if(_outbuffer.empty()) return;
            }
            else if(n==0)
            {
                //没有发送数据
                break;
            }
            else
            {
                //根据错误码分情况讨论
                if(errno == EAGAIN)
                {
                    break;//对端缓冲区被写满了
                }
                else if(errno == EINTR)
                {
                    //信号中断
                    continue;
                }
                else
                {
                    //异常处理
                    Excepter();
                    return;
                }
            }

            //到了此处，要么是发送完毕了，要么是对端缓冲区被写满了
            if(!_outbuffer.empty())
            {
                //说明对端缓冲区被写满了，将写放入epoller中
                Owner()->EnableReadWrite(_sockfd , true, true);
            }
            else
            {
                //发送完毕，关闭对写的关心
                Owner()->EnableReadWrite(_sockfd , true, false);
            }
        }
    }
    void Excepter()
    {
        //出现异常就将这个文件描述符从_connections 中移除
        Owner()->DelConnection(_sockfd);
    }

private:
};